package com.foodev.maven.gwt;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;


/**
 * Runs the GWT hosted mode browser.
 * 
 * @execute phase="process-resources"
 * @goal shell
 * @requiresDependencyResolution test
 * @author Martin Algesten
 */
public class ShellMojo extends AbstractGwtScriptMojo {

    /**
     * Prevents the embedded Tomcat server from running, even if a port is specified
     * 
     * @parameter
     */
    private boolean noserver = false;

    /**
     * Runs an embedded Tomcat instance on the specified port (defaults to 8888)
     * 
     * @parameter
     */
    private int port = -1;

    /**
     * Allows the user to browse URLs that match the specified regexes (comma or space separated)
     * 
     * @parameter
     */
    private String whiteList;

    /**
     * Prevents the user browsing URLs that match the specified regexes (comma or space separated)
     * 
     * @parameter
     */
    private String blackList;

    /**
     * Specifies a different embedded web server to run (must implement ServletContainerLauncher)
     * 
     * @parameter
     */
    private String server;

    /**
     * Automatically launches the specified URL
     * 
     * @parameter
     */
    private String startupUrl;


    /**
     * Helper class for extracting the libs.
     */
    private NativeLibsExtractor extractor = new NativeLibsExtractor();


    public void execute() throws MojoExecutionException, MojoFailureException {

        try {

            extractor.extractNativeLibs(findNativeZip());

            File file = createScriptFile("shell");
            FileWriter fwriter = new FileWriter(file);
            PrintWriter writer = new PrintWriter(fwriter);

            // shell should not keep the 'target/classes'
            List<String> classpath = filterClasspath(buildClasspath(), true);

            startScript(writer);

            writeOutputDirs(writer);
            writeClasspath(writer, classpath);

            writeCommand(writer);

            writer.close();
            fwriter.close();

            int exitValue = executeProcess(gwtHome, new String[] { file.getAbsolutePath() });

            if (exitValue != 0)
                throw new MojoExecutionException("GWT shell failed." + " Exit value: " + exitValue);

        } catch (MojoExecutionException e) {

            throw e;

        } catch (Exception e) {

            getLog().error(e);

            throw new MojoFailureException("Failed to run GWT shell.");

        }

    }


    private void writeOutputDirs(PrintWriter writer) throws IOException {

        if (isWindows()) {
            writer.print("set OUTPUTDIRS=");
        } else {
            writer.print("export OUTPUTDIRS=");
        }

        writer.println(project.getBuild().getOutputDirectory() + "," + project.getBuild().getTestOutputDirectory());

    }


    /**
     * Writes the hosted mode command to the script.
     * 
     * @param writer
     *            The writer to write the command to.
     * @throws IOException
     *             if something goes wrong when writing.
     */
    private void writeCommand(PrintWriter writer) throws IOException, DependencyResolutionRequiredException,
            MojoExecutionException {

        writeJavaCommand(writer);

        if (isMac()) {
            writer.write(" -XstartOnFirstThread");
            writer.write(" -d32");
        }

        writeSharedVMArgs(writer);

        // writer.write(" com.google.gwt.dev.HostedMode");
        writer.write(" " + ClasspathFixShellLauncher.class.getName());

        writeSharedArgs(writer, webappSrc);

        if (noserver)
            writer.write(" -noserver");

        if (port != -1)
            writer.write(" -port " + port);

        if (whiteList != null)
            writer.write(" -whiteList " + whiteList);

        if (blackList != null)
            writer.write(" -blackList " + blackList);

        if (server == null) {
            writer.write(" -server " + MushedClasspathJettyLauncher.class.getName());
        } else {
            writer.write(" -server " + server);
        }

        if (startupUrl != null)
            writer.write(" -startupUrl " + startupUrl);

        writeModules(writer);

        writer.println();

    }


}
